feat(canvas): 完善旧版 CanvasContext 跨端能力并统一触摸手势与 label 激活 - #306
Conversation
c16375e to
9dd5b29
Compare
|
@dos1in review |
35f9a8d to
d58e3fe
Compare
|
@dos1in 本来是想修改 Canvas 上的小问题,这下干脆把整个 Tap 事件按照微信小程序对齐了一遍。可以再 review 了 |
useTouchEvents.js#L26-L52
|
|
1. [P1] 判重改为按「页面 + 宿主组件实例 + canvas-id」在模块作用域的 新增 2. [P1] 动态切换 重装监听器这件事保留(passive 只能在注册时决定),但推迟到当前序列以 新增 3. [P1] iOS 在主线程解码并写入最大 32 MB 图片 解码 + 落盘抽成 同一个问题另外两端也有,一并改了(这两条不在 review 列表里):
Android 新增 5 例、iOS 新增 3 例单测,覆盖真实写盘产物、签名不匹配时不落盘、success/fail 各自的 complete 载荷,以及 iOS 的重活确实不在调用线程上完成。 4. [P2]
还有一处同源的偏离没动,想听下你的意见:微信的 验证:
|
|
|
第二轮四条已修( 你提的四条
自查另外发现的五条
已知未修runtime 在导出途中销毁时,Android/iOS 会把已写成的临时文件留在 tmp(回调本身正确丢弃)。Harmony 有 generation 可以顺手删,另两端没有等价 epoch,要检测得改 其余:单次文件 IO 无 deadline;Android/iOS 的 appId→锁表只增不减;iOS 的陈旧判定押在「 验证
新增行为测试都做了变异验证(去掉修复必须变红):让出重试 3 条、归属解析 2 条、getActions 守卫 1 条。 真机第一轮有两条红,都查了归属: |
|
|
第三轮四条和后续独立复审发现的问题都已闭环,最终修复在
本轮另外新增了两项实现与验证:
在此之后又做了一轮完整独立 review,继续修了 layout → backing store 预算绕过、动态 resolver、小游戏替换后的 render 资源残留、callback / RAF / ImageData 生命周期、iOS Unicode Base64 预算绕过,以及 Canvas2D setter/readback、save/restore/reset/resize 和旧 WebKit fallback。最终独立复查没有留下未闭环 finding。 验证:
|
7db3af6 to
9d08111
Compare
|
上一条之后又做了几轮独立复审,修复已经 amend 进同一个 commit(现为 1. 多指下的 原实现在第二根手指按下时立刻抑制 同时明确不采用 glass-easel 按 2. 同一个探针实测:越过位移阈值后,之后每一条 3. 节点卸载后仍会补造长按
4. HarmonyOS 编译回归 本 PR 给 5. JSSDK 重新生成 上面的手势改动落在 文档同步:触摸事件与手势第 1、3、6、7 节按上述语义重写;Canvas 运行架构补充了 |
9d08111 to
3cbf926
Compare
抬手时祖先的合成 tap 已经派发;稍后的自定义组件 click 即使调用 stopPropagation(),也无法阻止之前那条触摸事件对应的祖先 tap。这是事件冒泡语义回退。
|
旧版 wx.createCanvasContext() 补齐三端能力。canvas-id 按「页面 + 自定义组件实例」登记, 归属与 active 状态走 DOM property,不进入小程序事件的 target.dataset。组件根节点承载小程序 声明的 id、dataset 和布局,内部 HTMLCanvasElement 承载绘图,两者用共享的 DOM contract 显式 关联,SelectorQuery 的 node 不会误取 slot 里的 canvas。 绘制、像素读写与导出按真实 canvas 元素串行,不同 canvas 互不阻塞;作用域内的节点 lookup 单独 排队,避免后发请求越过还在等节点挂载的先发请求。Canvas 2D 状态以渲染层宿主 context 为权威, 逻辑层提供同步 optimistic getter 并以单调序号接收 readback,迟到反馈不覆盖新值;宿主缺少 reset() 时重设同尺寸 backing store 完成全量重置。 位图与 JSON 传输预算收拢到 @dimina/common 一处,组件 renderWidth/renderHeight、布局同步、 node width/height setter、离屏与小游戏创建、legacy 像素 API 和 canvasToTempFilePath 共用同一 组限制,超限在分配输出位图与编码之前失败。 Android、iOS、HarmonyOS 的导出请求绑定 app owner 与 runtime generation:退出或重启先推进 generation 并取消尚未开始的请求,已开始的继续占用并发与字节配额,旧 generation 的结果不投递、 已发布的文件立即删除,success/fail 与 complete 在同一串行域结算。 draw(reserve) 只保留像素、不保留绘图状态:渲染层每批开一层基线 save 帧,下批开始时弹回默认 样式、变换与裁剪区,画面不动;批内未配平的 restore() 停在批边界,弹不走基线帧。 触摸手势统一由 touchGestures 合成 tap/longpress/longtap/canceltap,按 owner 记账触点,不再 依赖全局 event.touches;label 默认不抑制内层组件的激活态。取消语义按微信实测对齐:越过位移 阈值后每条 touchmove 各发一条 canceltap,touchend 再比一次起终点距离、超阈值改发 canceltap, 这两条补发路径只在整段序列还没发过 canceltap 时生效;额外触点只停长按计时器,不取消先落手指 的 tap。节点卸载时进行中的序列仍等真实终态收口,但立即停掉长按计时器,不给已离树的节点补造 longpress/longtap。一个手势所有者只维护一条序列,不采用 glass-easel 按 identifier 逐触点 记账的模型。自定义组件的宿主节点接入同一条链路,由 ComponentHost 用 useTouchEvents 安装,不再 靠原生 click 派发 tap —— click 排在祖先的合成 tap 之后,宿主上的 catchtap 拦不住祖先的 bindtap。 DMPContainerBridgesModule 上移 currentAppId() 为 protected,Image/Video/Screen/Http 四个 子类删除各自逐字相同的 private 实现:ArkTS 不允许子类收窄继承成员的可见性。 新增 docs/canvas-architecture.md、docs/touch-event-architecture.md 记录上述不变量。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
3cbf926 to
b6b6fce
Compare
|
P1 已修 比你说的还严重一点:合成 tap 那套会直接忽略真指针产生的 click( 改法是让宿主节点直接用 新增 P2 没改 官方类型写的是取值范围为 另外提一句: |
|
@dos1in 辛苦再次 Review |
问题摘要
详细问题[P1] iOS CI 固定依赖
|
这个 PR 做了什么
补齐旧版
wx.createCanvasContext()在 Android、iOS、HarmonyOS、Web 四端的能力,顺带把 canvas 会用到的触摸事件和label点击对齐微信的行为。新老编译包都能跑。Canvas
save/restore、图片加载、像素读写、导出 PNG / JPEG,跨批次的状态也对齐了微信。canvas-id按页面和自定义组件实例隔离,同名 canvas 不会互相串;动态改canvas-id或type会正确重新绑定。requestAnimationFrame、图片、2D 状态回读和上屏 / 离屏的生命周期。触摸和 label
tap、longpress、longtap、canceltap不再直接拿浏览器的click当小程序tap,改成从触摸序列合成——这样catchtap才能真正拦住外层的bindtap。程序化点击、键盘和无障碍触发仍然走click兜底。canceltap;没有touchmove时(被preventDefault吞掉,或系统把移动并进了抬手)在touchend再按起点终点复查一次。这两条都是按微信实测对齐的。catchtap会排在祖先合成的tap之后,拦不住祖先。label点到控件时直接激活对应控件,不再调target.click()产生第二次tap;容器事件的currentTarget、id、dataset归到真正绑定事件的那个节点。这次没做
capture-bind/capture-catch和mut-bind还没实现,本 PR 不碰捕获阶段。tap的时机微信没有公开定义,这里只让建立序列的第一根手指产生tap,不采用 glass-easel 按identifier逐触点记账的模型。验证
分支已 rebase 到
main最新的2d7b9ea,冲突只有两处新增用例登记,按并集解决。以下都是在b6b6fce上实际跑出来的:pnpm lint、production build、git diff --check通过。pnpm generate:sdk从 production dist 重新生成,包内service.js、pageFrame.js与 container dist 逐字节一致。设计细节见 Canvas 运行架构 和 触摸事件与手势。